package com.bysc.cmsservice.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bysc.baseservice.handler.BaiYunException;
import com.bysc.cmsservice.entity.StudyData;
import com.bysc.cmsservice.entity.StudyType;
import com.bysc.cmsservice.entity.vo.StudyDataQueryVo;
import com.bysc.cmsservice.entity.vo.StudyFormVo;
import com.bysc.cmsservice.service.StudyDataService;
import com.bysc.cmsservice.service.StudyTypeService;
import com.bysc.commonutils.ResultCode;
import com.bysc.commonutils.Results;
import com.bysc.commonutils.constant.MessageConstant;
import com.bysc.commonutils.utils.JwtUtils;
import com.bysc.commonutils.vo.PageResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.bysc.commonutils.constant.RedisConstant.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author kkk
 * @since 2024-05-28
 */
@RestController
@Api(tags = "学习资料管理")
@RequestMapping("/studyservice/study-data")
public class StudyDataController {

    @Autowired
    private StudyDataService studyDataService;
    @Autowired
    private StudyTypeService studyTypeService;
    @Autowired
    private RedisTemplate redisTemplate;

    @ApiOperation(value = "根据id删除资料")
    @DeleteMapping("deleteStudyDataById/{id}")
    public Results deleteStudyDataById(@ApiParam(name = "id", value = "资料id", required = true) @PathVariable String id) {
        try {
            StudyData studyData = studyDataService.getById(id);
            if (studyData != null) {
                studyDataService.removeById(id);
                //删除zset中的数据
                redisTemplate.opsForZSet().remove("study_score", id);
            }
            return Results.ok().data("id", studyData.getId()).message(MessageConstant.DELETE_STUDYDATE_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaiYunException(ResultCode.ERROR, MessageConstant.DELETE_STUDYDATE_FAIL);
        }
    }

    /**
     * 分页查询我点赞的学习资料
     *
     * @return
     */
    @ApiOperation(value = "分页查询我点赞的学习资料")
    @GetMapping("getStudyDataByLike/{page}/{limit}")
    public Results getStudyDataByLike(@ApiParam(name = "page", value = "查询页数", required = true)
                                      @PathVariable Integer page, @ApiParam(name = "limit", value = "查询数量", required = true)
                                      @PathVariable Integer limit, HttpServletRequest request) {
        String userId = JwtUtils.getMemberIdByJwtToken(request);
        Set studyIds = redisTemplate.opsForSet().members(STUDY_DATA_USER_LIKE + userId);
        if (studyIds == null || studyIds.size() == 0) {
            return null;
        }
        // 计算分页的起始和结束索引
        int startIndex = (page - 1) * limit;
        int endIndex = Math.min(startIndex + limit, studyIds.size());
        // 返回当前页的列表
        List list = new ArrayList<>(studyIds);
        List subList = list.subList(startIndex, endIndex);
        ArrayList<StudyData> studys = new ArrayList<>();
        for (Object studyId : subList) {
            StudyData study = null;
            study = studyDataService.getById((String) studyId);
            if (study != null) {
                String key = STUDY_DATA + study.getId();
                String likeSKey = STUDY_DATA_USER_LIKE + userId;
                String collectSKey = STUDY_DATA_USER_COLLECT + userId;
                Integer like = (Integer) redisTemplate.opsForHash().get(key, _LIKE);
                Integer collect = (Integer) redisTemplate.opsForHash().get(key, _COLLECT);
                Integer view = (Integer) redisTemplate.opsForHash().get(key, _VIEW);
                study.setLikes(like);
                study.setCollections(collect);
                study.setViews(view);
                study.setIsLiked(redisTemplate.opsForSet().isMember(likeSKey, study.getId()));
                study.setIsCollected(redisTemplate.opsForSet().isMember(collectSKey, study.getId()));
            }
            studys.add(study);
        }
        PageResult pageResult = new PageResult((long) studyIds.size(), studys.size(), studys, page);
        return Results.ok().data("list", pageResult).message(MessageConstant.QUERY_STUDYDATE_SUCCESS);
    }

    /**
     * 分页查询我收藏的学习资料
     *
     * @return
     */
    @ApiOperation(value = "分页查询我收藏的学习资料")
    @GetMapping("getStudyDataByCollect/{page}/{limit}")
    public Results getStudyDataByCollect(@ApiParam(name = "page", value = "查询页数", required = true)
                                         @PathVariable Integer page, @ApiParam(name = "limit", value = "查询数量", required = true)
                                         @PathVariable Integer limit, HttpServletRequest request) {
        String userId = JwtUtils.getMemberIdByJwtToken(request);
        Set studyIds = redisTemplate.opsForSet().members(STUDY_DATA_USER_COLLECT + userId);
        if (studyIds == null || studyIds.size() == 0) {
            return null;
        }
        // 计算分页的起始和结束索引
        int startIndex = (page - 1) * limit;
        int endIndex = Math.min(startIndex + limit, studyIds.size());
        // 返回当前页的列表
        List list = new ArrayList<>(studyIds);
        List subList = list.subList(startIndex, endIndex);
        ArrayList<StudyData> studys = new ArrayList<>();
        for (Object studyId : subList) {
            StudyData study = null;
            study = studyDataService.getById((String) studyId);
            if (study != null) {
                String key = STUDY_DATA + study.getId();
                String likeSKey = STUDY_DATA_USER_LIKE + userId;
                String collectSKey = STUDY_DATA_USER_COLLECT + userId;
                Integer like = (Integer) redisTemplate.opsForHash().get(key, _LIKE);
                Integer collect = (Integer) redisTemplate.opsForHash().get(key, _COLLECT);
                Integer view = (Integer) redisTemplate.opsForHash().get(key, _VIEW);
                study.setLikes(like);
                study.setCollections(collect);
                study.setViews(view);
                study.setIsLiked(redisTemplate.opsForSet().isMember(likeSKey, study.getId()));
                study.setIsCollected(redisTemplate.opsForSet().isMember(collectSKey, study.getId()));
            }
            studys.add(study);
        }
        PageResult pageResult = new PageResult((long) studyIds.size(), studys.size(), studys, page);
        return Results.ok().data("list", pageResult).message(MessageConstant.QUERY_STUDYDATE_SUCCESS);
    }

    @ApiOperation(value = "带条件分页查询资料")
    @PostMapping("getStudyDataByQueryVo/{page}/{limit}")
    public Results getStudyDataByQueryVo(@ApiParam(name = "page", value = "查询页数", required = true)
                                         @PathVariable Integer page, @ApiParam(name = "limit", value = "查询数量", required = true)
                                         @PathVariable Integer limit, @ApiParam(name = "queryVo", value = "查询条件", required = false)
                                         @RequestBody StudyDataQueryVo queryVo, HttpServletRequest
                                                 request) {

        try {
            String id = queryVo.getId();
            String parentTypeId = queryVo.getParentTypeId();
            String typeId = queryVo.getTypeId();
            String value = queryVo.getValue();
            Boolean isPrivate = queryVo.getIsPrivate();
            Page<StudyData> infoPage = new Page<>(page, limit);
            LambdaQueryWrapper<StudyData> wrapper = new LambdaQueryWrapper<>();
            if (!StringUtils.isEmpty(id)) {
                wrapper.eq(StudyData::getId, id);
            }
            if (!StringUtils.isEmpty(parentTypeId)) {
                wrapper.eq(StudyData::getParentTypeId, parentTypeId);
            }
            if (!StringUtils.isEmpty(typeId)) {
                wrapper.eq(StudyData::getTypeId, typeId);
            }
            if (isPrivate != null) {
                wrapper.eq(StudyData::getIsPrivate, isPrivate);
            }
            if (!StringUtils.isEmpty(value)) {
                wrapper.like(StudyData::getTitle, value).or().like(StudyData::getDescription, value);
            }
            wrapper.orderByDesc(StudyData::getGmtCreate);
            IPage<StudyData> iPage = studyDataService.page(infoPage, wrapper);
            for (StudyData record : iPage.getRecords()) {
                if (record != null) {
                    StudyType studyType = studyTypeService.getById(record.getParentTypeId());
                    if (studyType != null) {
                        record.setParentTypeName(studyType.getName());
                    }
                    StudyType studyType1 = studyTypeService.getById(record.getTypeId());
                    if (studyType1 != null) {
                        record.setTypeName(studyType1.getName());
                    }
                    String key = STUDY_DATA + record.getId();
                    String userId = JwtUtils.getMemberIdByJwtToken(request);
                    String likeSKey = STUDY_DATA_USER_LIKE + userId;
                    String collectSKey = STUDY_DATA_USER_COLLECT + userId;
                    Integer like = (Integer) redisTemplate.opsForHash().get(key, _LIKE);
                    Integer collect = (Integer) redisTemplate.opsForHash().get(key, _COLLECT);
                    Integer view = (Integer) redisTemplate.opsForHash().get(key, _VIEW);
                    record.setLikes(like);
                    record.setCollections(collect);
                    record.setViews(view);
                    record.setIsLiked(redisTemplate.opsForSet().isMember(likeSKey, record.getId()));
                    record.setIsCollected(redisTemplate.opsForSet().isMember(collectSKey, record.getId()));
                }
                //查学习资料详细信息
            }
            return Results.ok().data("list", iPage).message(MessageConstant.QUERY_STUDYDATE_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaiYunException(ResultCode.ERROR, MessageConstant.QUERY_STUDYDATE_FAIL);
        }
    }

    @ApiOperation(value = "增加浏览量")
    @PutMapping("updateViewCount/{id}")
    public Results updateViewCount(@ApiParam(name = "id", value = "资料id", required = true) @PathVariable String id) {
        try {
            // 构造Redis的key
            String key = STUDY_DATA + id;
            // 使用RedisTemplate递增浏览量
            redisTemplate.opsForHash().increment(key, _VIEW, 1);
            return Results.ok().message(MessageConstant.EDIT_STUDYDATE_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaiYunException(ResultCode.ERROR, MessageConstant.EDIT_STUDYDATE_FAIL);
        }
    }

    @ApiOperation(value = "根据id修改资料信息")
    @PutMapping("updateStudyDataById/{id}")
    public Results updateStudyDataById(@ApiParam(name = "StudyInfo", value = "资料信息", required = true) @RequestBody StudyData studyData) {
        try {
            studyDataService.updateById(studyData);
            return Results.ok().message(MessageConstant.EDIT_STUDYDATE_SUCCESS);
        } catch (Exception e) {
            throw new BaiYunException(ResultCode.ERROR, MessageConstant.EDIT_STUDYDATE_FAIL);
        }
    }

    @ApiOperation("获取综合排名前十学习资料")
    @GetMapping("getStudyDataByScore")
    public Results getStudyDataByScore() {
        // 查询 Redis 中的排名前十的学习资料（按热度分数）
        Set<String> studyIds = redisTemplate.opsForZSet().reverseRange("study_score", 0, 9);
        List<StudyData> studyDataList = studyDataService.list(new QueryWrapper<StudyData>().in("id", studyIds));
        // 将 MongoDB 查询结果按照 Redis 中的顺序进行排序
        Map<String, StudyData> studyMap = new HashMap<>();
        for (StudyData studyData : studyDataList) {
            studyData.setScore(redisTemplate.opsForZSet().score("study_score", studyData.getId()));
            studyMap.put(studyData.getId(), studyData);
        }
        // 根据 Redis 中的顺序重新排序
        List<StudyData> sortedstudys = new ArrayList<>();
        for (String studyId : studyIds) {
            if (studyMap.containsKey(studyId)) {
                sortedstudys.add(studyMap.get(studyId));
            }
        }
        return Results.ok().data("list", sortedstudys).message("查询学习资料成功");
    }


    @ApiOperation(value = "新增学习资料")
    @PostMapping("addStudyData")
    @CacheEvict(value = "user", key = "'CollegeAndMajor'", allEntries = true)
    public Results addStudyData(@ApiParam(name = "studyFormVo", value = "资料信息", required = true) @RequestBody StudyFormVo studyFormVo) {
        try {
            StudyData studyData = new StudyData();
            BeanUtils.copyProperties(studyFormVo, studyData);
            studyDataService.save(studyData);
            return Results.ok().data("id", studyData.getId()).message(MessageConstant.ADD_STUDYDATE_SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaiYunException(ResultCode.ERROR, MessageConstant.ADD_STUDYDATE_FAIL);
        }
    }
}

